package mqtt_sub

import (
	"encoding/json"
	"fmt"
	"log"
	"modbus-dtu-plugin/modbus"
	"modbus-dtu-plugin/zaplog"
	"os"
	"strings"

	mqtt "github.com/eclipse/paho.mqtt.golang"
	"github.com/go-basic/uuid"
	"github.com/panjf2000/ants/v2"
	"github.com/spf13/viper"
	"go.uber.org/zap"
)

var mqtt_client mqtt.Client

func Init() {
	listenMQTT()
}

func listenMQTT() {
	broker := os.Getenv("MQTT_HOST")
	if broker == "" {
		broker = viper.GetString("mqtt.broker")
	}
	clientid := uuid.New()
	fmt.Println("sub_mqtt clientid", clientid)
	username := viper.GetString("mqtt.username")
	password := viper.GetString("mqtt.password")

	var connectLostHandler mqtt.ConnectionLostHandler = func(client mqtt.Client, err error) {
		fmt.Printf("Connect lost: %v", err)
	}
	opts := mqtt.NewClientOptions()
	opts.SetUsername(username)
	opts.SetPassword(password)
	opts.SetClientID(clientid)
	opts.AddBroker(broker)
	opts.SetAutoReconnect(true) //自动重连
	opts.SetOrderMatters(false)
	opts.OnConnectionLost = connectLostHandler
	opts.SetOnConnectHandler(func(c mqtt.Client) {
		log.Println("sub MQTT客户端连接成功...", broker)
	})
	p, _ := ants.NewPool(viper.GetInt("mqtt.pool")) //设置并发池
	log.Println("mqtt客户端订阅处理的并发池大小为", viper.GetInt("mqtt.subscribe_pool"))
	opts.SetDefaultPublishHandler(func(c mqtt.Client, m mqtt.Message) {
		_ = p.Submit(func() {
			MsgProc(c, m)
		})
	})
	mqtt_client = mqtt.NewClient(opts)
	if token := mqtt_client.Connect(); token.Wait() && token.Error() != nil {
		log.Println("mqtt客户端连接异常...", viper.GetString("mqtt.broker"), token.Error())
		os.Exit(1)
	}
	// 订阅主题
	if token := mqtt_client.Subscribe(viper.GetString("mqtt.topic_to_subscribe"), 0, nil); token.Wait() && token.Error() != nil {
		log.Println("mqtt订阅异常异常...", viper.GetString("mqtt.topic_to_subscribe"), token.Error())
		os.Exit(1)
	} else {
		log.Println("mqtt订阅成功...", viper.GetString("mqtt.topic_to_subscribe"))
	}
}

// 接收订阅的消息进行处理
func MsgProc(c mqtt.Client, m mqtt.Message) {
	payload := m.Payload()
	log.Println("收到订阅消息", string(payload))
	// plugin/modbus/#
	// 获取网关id
	d := strings.Split(m.Topic(), "/")
	gatewayId := d[len(d)-1]
	log.Println("网关id是:", gatewayId)
	// 判断网关连接是否存在
	if _, ok := modbus.GatewayConn[gatewayId]; !ok {
		log.Println("网关连接不存在")
		return
	} else {
		log.Println("网关连接存在")
	}
	// 获取网关连接
	conn := modbus.GatewayConn[gatewayId]
	// 解析payload为payloadMap
	var payloadMap map[string]interface{}
	err := json.Unmarshal(payload, &payloadMap)
	if err != nil {
		log.Println("json unmarshal failed", err.Error())
		return
	}
	// 遍历payloadMap
	for subDeviceAddr, value := range payloadMap {
		valueMap := value.(map[string]interface{})
		// 遍历conn的子设备
		for subDeviceKey, subDevice := range conn.SubDeviceReqMap {
			if subDevice.SubDeviceAddr == subDeviceAddr {
				// 遍历valueMap
				for key := range valueMap {
					// 组装发送
					err := conn.SendRequestToDevice(subDeviceKey, key, valueMap[key])
					if err != nil {
						zaplog.Logger.Error("send request to device failed", zap.Error(err))
					}
				}
			}
		}
	}

}
